#include "postprocess/post_process_variable.h"

PostProcessCommon::PostProcessCommon() {}

PostProcessCommon::~PostProcessCommon() {}

float PostProcessCommon::Giou2D(const Box& b1, const Box& b2) {
  polygon_t poly1;
  polygon_t poly2;
  polygon_t poly3;

  for (auto pp : b1.polygon) {
    point_t p1{pp.x(), pp.y()};
    bg::append(poly1, p1);
    bg::append(poly3, p1);
  }

  for (auto pp : b2.polygon) {
    point_t p2{pp.x(), pp.y()};
    bg::append(poly2, p2);
    bg::append(poly3, p2);
  }

  polygon_t hull1;
  polygon_t hull2;
  bg::convex_hull(poly1, hull1);
  bg::convex_hull(poly2, hull2);

  std::deque<polygon_t> output;
  auto isOK = bg::intersection(hull1, hull2, output);
  if (!isOK) {
    // throw std::logic_error("polygen intersection error!");
  }

  double i{0};
  BOOST_FOREACH (polygon_t const& p, output) {
    i += bg::area(p);
  }  // 求交面积

  auto area1 = bg::area(hull1);
  auto area2 = bg::area(hull2);
  auto u{area1 + area2 - i};  // union面积

  // 求凸包
  polygon_t hull3;
  bg::convex_hull(poly3, hull3);

  auto c{bg::area(hull3)};  // 凸包面积

  if (u == 0 || c == 0) {
    // throw std::out_of_range("Invalid giou, u is 0 or c is 0");
  }

  return i / u - (c - u) / c;  // GIOU
}

float PostProcessCommon::Iou2D(const Box& b1, const Box& b2) {
  polygon_t poly1;
  polygon_t poly2;

  for (auto pp : b1.polygon) {
    point_t p1{pp.x(), pp.y()};
    bg::append(poly1, p1);
  }

  for (auto pp : b2.polygon) {
    point_t p2{pp.x(), pp.y()};
    bg::append(poly2, p2);
  }

  polygon_t hull1;
  polygon_t hull2;
  bg::convex_hull(poly1, hull1);
  bg::convex_hull(poly2, hull2);

  std::deque<polygon_t> output;
  auto isOK = bg::intersection(hull1, hull2, output);
  if (!isOK) {
    // throw std::logic_error("polygen intersection error!");
  }

  double i{0};
  BOOST_FOREACH (polygon_t const& p, output) {
    i += bg::area(p);
  }  // 求交面积

  auto area1 = bg::area(hull1);
  auto area2 = bg::area(hull2);
  auto u{area1 + area2 - i};  // union面积
  if (u == 0) {
    // throw std::out_of_range("Invalid iou, u is 0");
  }

  return i / u;  // IOU
}
